package init.utils;

import init.config.Config;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;

public class SqlScriptUtils {
	
	private static String getRootDir() throws URISyntaxException{
		return SqlScriptUtils.class.getResource("/").toURI().getPath();
	}
	
	private static File getSqlDir() throws URISyntaxException{
		String path = getRootDir() + Config.SQL_PATH;
		return new File(path);
	}
	
	private static File getCreateTableDir() throws URISyntaxException{
		String path = getRootDir() + Config.SQL_CREATE_TABLE_PATH;
		return new File(path);
	}
	
	private static File getDropTableDir() throws URISyntaxException{
		String path = getRootDir() + Config.SQL_DROP_TABLE_PATH;
		return new File(path);
	}
	
	/**
	 * 排序文件，根据文件最后的数字位，来排序，用于按顺序执行脚本
	 * @return
	 * @throws URISyntaxException 
	 */
	public static File[] sortSqlFiles() throws URISyntaxException{
		//sql文件
		File[] files = getSqlDir().listFiles(new SqlFilter());
		
		final Pattern pattern = Pattern.compile(".*\\.(\\d+)\\." + Config.SCRIPT_SUFFIX); 
		
		Arrays.sort(files, new Comparator<File>(){
			@Override
			public int compare(File f1, File f2) {
				Matcher mat1 = pattern.matcher(f1.getName());
				Matcher mat2 = pattern.matcher(f2.getName());
				if(!mat1.matches() && mat2.matches()){
					return 1;
				}else if(mat1.matches() && !mat2.matches()){
					return -1;
				}else if(!mat1.matches() && !mat2.matches()){
					return 0;
				}
				
				Integer idx1 = Integer.valueOf(mat1.group(1));
				Integer idx2 = Integer.valueOf(mat2.group(1));
				return idx1.compareTo(idx2);
			}
		});
		return files;
	}
	
	
	public static File[] dropFiles() throws URISyntaxException{
		//drop sql 文件
		return getDropTableDir().listFiles(new SqlFilter());
	}
	
	public static File[] createFiles() throws URISyntaxException{
		//create sql 文件
		return getCreateTableDir().listFiles(new SqlFilter());
	}
	
	public static File[] sqlFiles(String[] filenames) throws URISyntaxException{
		return getSqlDir().listFiles(new SqlFilter(filenames));
	}
	
	
	public static void execute(File file, ExecuteUtils executer){
		BufferedReader reader = null;
		String line = "";
		StringBuffer buffer = new StringBuffer();
		
		try {
			reader = new BufferedReader(new FileReader(file));
			
			executer.getConnection().setAutoCommit(false);
			//排除单行注释
			while((line = reader.readLine())!=null){
				line = line.trim();
				
				if(line.startsWith("--")){
					continue;
				}
				if(line.contains("--")){
					int i = line.indexOf("--");
					line = line.substring(0, i);
				}
				if(line.endsWith(";")){
					buffer.append(line.substring(0, line.length()-1));
					executer.execute(buffer.toString());
					buffer.delete(0, buffer.length());
				}else{
					buffer.append(line+" ");
				}
			}
			
			executer.getConnection().commit();
		} catch (SQLException es){
			LogUtils.logging(SqlScriptUtils.class, buffer.toString());
			es.printStackTrace();
			try {
				executer.getConnection().rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
			try {
				executer.getConnection().rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			if(reader!=null){
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

/**
 * 排除掉目录或非sql文件
 * @author Administrator
 *
 */
class SqlFilter implements FileFilter{
	private String[] filenames;
	
	public SqlFilter(){
		super();
	}
	
	public SqlFilter(String[] filenames){
		super();
		this.filenames = filenames;
	}
	
	private boolean isSqlFilename(File filename){
		if(filename.getName().endsWith("."+Config.SCRIPT_SUFFIX)){
			return true;
		}
		return false;
	}

	@Override
	public boolean accept(File pathname) {
		if(!pathname.isFile()){
			return false;
		}
		//未设置sql文件名
		if(ArrayUtils.isEmpty(filenames)){
			return this.isSqlFilename(pathname);
		}else{
			if(ArrayUtils.contains(filenames, pathname.getName())){
				return this.isSqlFilename(pathname);
			}else{
				return false;
			}
		}
	}
}
